package com.example.admin.mybledemo.ota;

import com.example.admin.mybledemo.BleRssiDevice;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import cn.com.heaton.blelibrary.ble.Ble;
import cn.com.heaton.blelibrary.ble.BleLog;
import cn.com.heaton.blelibrary.ble.callback.BleScanCallback;
import cn.com.heaton.blelibrary.ble.model.BleDevice;

/**
 * Boot模式设备扫描器
 */
public class BootDeviceScanner {
    
    private static final String TAG = "BootDeviceScanner";
    private static final int SCAN_TIMEOUT_MS = 15000;
    private static final int RETRY_DELAY_MS = 2000;
    private static final int MAX_RETRY_COUNT = 3;
    
    private ScheduledExecutorService executorService;
    private ScheduledFuture<?> timeoutTask;
    private boolean isScanning = false;
    private int retryCount = 0;
    private BootDeviceScanListener scanListener;
    private RandomMacManager randomMacManager;
    
    public interface BootDeviceScanListener {
        void onBootDeviceFound(BleRssiDevice device);
        void onScanFailed(String errorMessage);
        void onScanTimeout();
        void onScanStatusUpdate(String message);
    }
    
    public BootDeviceScanner() {
        this.executorService = Executors.newSingleThreadScheduledExecutor();
        this.randomMacManager = RandomMacManager.getInstance();
    }
    
    public void setScanListener(BootDeviceScanListener listener) {
        this.scanListener = listener;
    }
    
    public void startScan() {
        if (isScanning) {
            BleLog.d(TAG, "Already scanning");
            return;
        }
        
        if (!randomMacManager.hasRandomMac()) {
            if (scanListener != null) {
                scanListener.onScanFailed("No random MAC generated");
            }
            return;
        }
        
        isScanning = true;
        retryCount = 0;
        
        BleLog.d(TAG, "Start scanning for Boot device: " + randomMacManager.getRandomMacString());
        
        if (scanListener != null) {
            scanListener.onScanStatusUpdate("Scanning for Boot device...");
        }
        
        performScan();
    }
    
    public void stopScan() {
        if (!isScanning) {
            return;
        }
        
        isScanning = false;
        
        if (timeoutTask != null && !timeoutTask.isCancelled()) {
            timeoutTask.cancel(true);
            timeoutTask = null;
        }
        
        Ble.getInstance().stopScan();
        
        BleLog.d(TAG, "Stop scanning Boot device");
        
        if (scanListener != null) {
            scanListener.onScanStatusUpdate("Scan stopped");
        }
    }
    
    public boolean isScanning() {
        return isScanning;
    }
    
    private void performScan() {
        timeoutTask = executorService.schedule(new Runnable() {
            @Override
            public void run() {
                if (isScanning) {
                    BleLog.d(TAG, "Scan timeout, retry: " + retryCount);
                    handleScanTimeout();
                }
            }
        }, SCAN_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        
        Ble.getInstance().startScan(new BleScanCallback<BleDevice>() {
            @Override
            public void onLeScan(BleDevice device, int rssi, byte[] scanRecord) {
                if (!isScanning) {
                    return;
                }
                
                boolean isBootDevice = randomMacManager.isBootModeDevice(
                    device.getBleAddress(), 
                    device.getBleName()
                );
                
                if (isBootDevice) {
                    BleLog.d(TAG, "Boot device found: " + device.getBleAddress());
                    
                    stopScan();
                    
                    BleRssiDevice bootDevice = new BleRssiDevice(device.getBleAddress(), device.getBleName());
                    bootDevice.setRssi(rssi);
                    
                    if (scanListener != null) {
                        scanListener.onBootDeviceFound(bootDevice);
                    }
                }
            }
            
            @Override
            public void onScanFailed(int errorCode) {
                BleLog.e(TAG, "Scan failed: " + errorCode);
                
                if (isScanning) {
                    stopScan();
                    
                    if (scanListener != null) {
                        scanListener.onScanFailed("Scan failed: " + errorCode);
                    }
                }
            }
        });
    }
    
    private void handleScanTimeout() {
        if (retryCount < MAX_RETRY_COUNT) {
            retryCount++;
            
            BleLog.d(TAG, "Retry scan " + retryCount + "/" + MAX_RETRY_COUNT);
            
            if (scanListener != null) {
                scanListener.onScanStatusUpdate("Retry " + retryCount + "/" + MAX_RETRY_COUNT);
            }
            
            executorService.schedule(new Runnable() {
                @Override
                public void run() {
                    if (isScanning) {
                        performScan();
                    }
                }
            }, RETRY_DELAY_MS, TimeUnit.MILLISECONDS);
            
        } else {
            BleLog.d(TAG, "Max retry reached");
            
            stopScan();
            
            if (scanListener != null) {
                scanListener.onScanTimeout();
            }
        }
    }
    
    public void reset() {
        stopScan();
        retryCount = 0;
    }
    
    public void release() {
        stopScan();
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
        }
    }
} 